package com.jfl.base;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.jfl.common.Constants;
import com.jfl.exception.BusinessException;
import com.jfl.exception.ValidateException;
import com.jfl.utils.ConvertUtil;
import com.jfl.utils.ExceptionUtil;
import com.jfl.utils.InstanceUtil;
/**
 * 基类service实现类
 *  
 * @author  赵炎
 * @version  [V1.00, 2018年12月3日]
 * @since V1.00
 */
public class BaseServiceImpl<T extends BaseModel, M extends BaseMapper<T>> extends ServiceImpl<BaseMapper<T>, T> implements BaseService<T>
{
    /**
     * logger 日志
     */
    protected Logger logger = LoggerFactory.getLogger(getClass());
    
    /**
     * mapper
     */
    @Autowired
    protected M mapper;
    

    @Transactional
    @Override
    public T update(T record) throws BusinessException, ValidateException
    {
        if (record.getId() != null)
        {
          record.setUpdateTime(new Date());
          this.mapper.updateById(record);  
        }
        else
        {
            record.setCreateTime(new Date());
            record.setUpdateTime(new Date());
            record.setUpdateBy(record.getCreateBy());
            this.mapper.insert(record);
        }
        return this.mapper.selectById(record.getId());
    }

    /**
     * 逻辑删除
     * @param ids
     * @param userId
     * @throws BusinessException
     * @throws ValidateException
     * @see com.jfl.base.BaseService#del(java.util.List, java.lang.Long)
     */
    @Override
    @Transactional
    public void del(List<Long> ids, Long userId) throws BusinessException, ValidateException
    {
        // lamda表达式 JDK1.8才支持
        ids.forEach(id -> del(id, userId));
    }

    /**
     * 逻辑删除
     * @param id
     * @param userId
     * @throws BusinessException
     * @throws ValidateException
     * @see com.jfl.base.BaseService#del(java.lang.Long, java.lang.Long)
     */
    @Override
    @Transactional
    public void del(Long id, Long userId) throws BusinessException, ValidateException
    {
        try
        {
            T record = this.queryById(id);
            record.setEnable(0);
            record.setUpdateBy(userId);
            record.setUpdateTime(new Date());
            this.mapper.updateById(record);
        }
        catch (Exception e)
        {
           throw new RuntimeException(e.getMessage(), e);
        }
        
    }

    /**
     * 物理删除
     * @param id
     * @throws BusinessException
     * @throws ValidateException
     * @see com.jfl.base.BaseService#delete(java.lang.Long)
     */
    @Override
    @Transactional
    public void delete(Long id) throws BusinessException, ValidateException
    {
        try
        {
            this.mapper.deleteById(id);
        }
        catch (Exception e)
        {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * 物理删除
     * @param entity
     * @return
     * @throws BusinessException
     * @throws ValidateException
     * @see com.jfl.base.BaseService#deleteByEntity(com.jfl.base.BaseModel)
     */
    @Override
    @Transactional
    public Integer deleteByEntity(T entity) throws BusinessException, ValidateException
    {
        Wrapper<T> wrapper = new UpdateWrapper<T>(entity);
        return this.mapper.delete(wrapper);
    }

    /**
     * 物理删除
     * @param columnMap
     * @return
     * @throws BusinessException
     * @throws ValidateException
     * @see com.jfl.base.BaseService#deleteByMap(java.util.Map)
     */
    @Override
    @Transactional
    public Integer deleteByMap(Map<String, Object> columnMap) throws BusinessException, ValidateException
    {
        return this.mapper.deleteByMap(columnMap);
    }

    /**
     * 根据Id查询
     * @param id
     * @return
     * @see com.jfl.base.BaseService#queryById(java.lang.Long)
     */
    @Override
    public T queryById(Long id)
    {   
        return this.mapper.selectById(id);
    }

    /**
     * 分页查询
     * @param params 其中params必须为数据库中字段
     * @return
     * @see com.jfl.base.BaseService#query(java.util.Map)
     */
    @Override
    public PageInfo<T> query(Map<String, Object> params)
    {
        // 默认当前页为1
        int pageNum = 1;
        // 默认页码大小为10
        int pageSize = 10;
        // 默认计算count
        String orderBy = null;
        if(params.get("pageNum") != null && StringUtils.isNotBlank(params.get("pageNum") + ""))
        {
            pageNum = Integer.valueOf(params.get("pageNum").toString());
            params.remove("pageNum");
        }
        if(params.get("pageSize") != null && StringUtils.isNotBlank(params.get("pageSize") + ""))
        {
            pageSize = Integer.valueOf(params.get("pageSize").toString());
            params.remove("pageSize");
        }
        if(params.get("orderBy")!= null && StringUtils.isNotBlank(params.get("orderBy") + ""))
        {
            orderBy = params.get("orderBy").toString();
            params.remove("orderBy");
        }
        // 设置分页的参数
        PageHelper.startPage(pageNum, pageSize, orderBy);
        // 有效数据
        params.put("enable", 1);
        // 根据条件查询
        List<T> list = this.mapper.selectByMap(params);
        // 分装成分页对象
        return new PageInfo<T>(list);
    }

    /**
     * 根据实体参数分页查询
     * @param entity
     * @param rowBounds
     * @return
     * @see com.jfl.base.BaseService#query(com.jfl.base.BaseModel, com.github.pagehelper.PageInfo)
     */
    @Override
    public PageInfo<T> query(T entity, PageInfo<T> rowBounds)
    {
        Page<T> page = new Page<T>();
        try
        {
            BeanUtils.copyProperties(page, rowBounds);
        }
        catch (Exception e)
        {
          logger.error(ExceptionUtil.getStackTraceAsString(e));
        }
        // List<Long> ids = this.mapper.selectIdPage(page,entity);
        return new PageInfo<T>(null);
    }

    /**
     * 根据参数查询
     * @param params
     * @return
     * @see com.jfl.base.BaseService#queryList(java.util.Map)
     */
    @Override
    public List<T> queryList(Map<String, Object> params)
    {
        // 根据参数获取全部数据的Id 从DB中查询
        List<Long> ids = this.mapper.selectIdPage(params);
        List<T> list = queryList(ids);
        return list;
    }

    /**
     * 根据Id查询 如果缓存中有则从缓存中获取，否则从DB中获取
     * @param ids
     * @return
     * @see com.jfl.base.BaseService#queryList(java.util.List)
     */
    @Override
    public List<T> queryList(List<Long> ids)
    {
        final List<T> list = Lists.newArrayList();
        if (ids != null)
        {
            // lamda表达式
            ids.forEach(id -> list.add(queryById(id)));
        }
        return list;
    }

    @Override
    public <K> List<K> queryList(List<Long> ids, Class<K> clazz)
    {
        final List<K> list = Lists.newArrayList();
        if(ids != null)
        {
            for (int i = 0; i < ids.size(); i++)
            {
                T t = queryById(ids.get(i));
                K k = InstanceUtil.to(t, clazz);
                list.set(i, k);
            }
        }
        return list;
    }

    /**
     * 根据实体参数查询
     * @param entity
     * @return
     * @see com.jfl.base.BaseService#queryList(com.jfl.base.BaseModel)
     */
    @Override
    public List<T> queryList(T entity)
    {
        // 先查出所有有关的id
        List<Long> ids = this.mapper.selectIdPage(entity);
        // 缓存中有则从缓存中取值，否则从数据库取值
        List<T> list = queryList(ids);
        return list;
    }

    /**
     * 从数据库中查询
     * @param params
     * @return
     * @see com.jfl.base.BaseService#queryFromDB(java.util.Map)
     */
    @Override
    public PageInfo<T> queryFromDB(Map<String, Object> params)
    {
        
        return null;
    }

    @Override
    public PageInfo<T> queryFromDB(T entity, PageInfo<T> rowBounds)
    {
        return null;
    }

    /**
     * 从数据库中查询
     * @param params 表字段
     * @return
     * @see com.jfl.base.BaseService#queryListFromDB(java.util.Map)
     */
    @Override
    public List<T> queryListFromDB(Map<String, Object> params)
    {
        return this.mapper.selectByMap(params);
    }

    @Override
    public PageInfo<T> selectList(PageRequest request, T record)
    {
        PageHelper.startPage(request.getPageNum(), request.getPageSize(), request.getOrderBy());
        QueryWrapper<T> wrapper = new QueryWrapper<T>();
        if (record != null)
        {
            wrapper = tranform(record);
            if(record.getParams() != null)
            {
                if(StringUtils.isNotBlank(record.getParams().get("beginTime") + "") && StringUtils.isNotBlank(record.getParams().get("endTime") + ""))
                {
                    wrapper.between("create_time", record.getParams().get("beginTime") , record.getParams().get("endTime"));
                }
            }
            
        }
        wrapper.eq("enable", 1);
        List<T> list = this.mapper.selectList(wrapper);
        return new PageInfo<T>(list);
    }

    /** 
     * 转换查询
     * @param record
     * @return
     * @see [类、类#方法、类#成员]
     */
    private QueryWrapper<T> tranform(T record)
    {
        QueryWrapper<T> wrapper = new QueryWrapper<T>();
        Field[] fields = record.getClass().getDeclaredFields();
        try
        {
            for (Field field : fields)
            {
                field.setAccessible(true);
                String fieldName = field.getName();
                String clazz = field.getType().getTypeName();
                Method method = record.getClass().getDeclaredMethod("get"+ fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1));
                Object obj = method.invoke(record);
                if(obj != null && StringUtils.isNotBlank(obj + ""))
                {
                    if ("java.lang.String".equals(clazz))
                    {
        
                        if("status".equals(fieldName))
                        {
                            wrapper.eq(ConvertUtil.underLine2Camel(fieldName), obj);
                        } 
                        else
                        {
                            wrapper.like(ConvertUtil.underLine2Camel(fieldName), obj);
                        }
                    }
                    else if ("java.lang.Integer".equals(clazz) || "java.lang.Short".equals(clazz) || "java.lang.Long".equals(clazz))
                    {
                        wrapper.eq(ConvertUtil.underLine2Camel(fieldName), obj);
                    } 
                }

                
            }
        }
        catch (Exception e)
        {
            logger.error("转换异常", e);
        }

        return wrapper;
    }
    
    /** 
     * 唯一性统一返回
     * @param record 参数对象
     * @param id 数据库中数据Id
     * @return "0"：存在  "1"：唯一
     */
    public String result(T record, Long id)
    {
      
        if(record != null && record.getId().longValue() != id.longValue())
        {
            return Constants.DATA_NOT_UNIQUE;
        }
        return Constants.DATA_UNIQUE;
    }

}